#include "function.h"
void getsfun(int clientfd,int filefd);
void readorder(char buf[],int len,int* closeflag,int clientfd){
    int u = 0;
    int t = 0;
    int z = 0;
    int i = 0;
    char order[1024]={0};
    char filename[1024]={0};
    memset(order,0,sizeof(order));
    memset(filename,0,sizeof(filename));
    for(;u<len;u++){
        while(buf[u]!=32&&u<len-1){
            order[t]=buf[u];
            t++;
            u++;
            if(buf[u]==32||u==len-1){
                z=u;
                u=len;
            }
        }
    }
    puts(order);
    for(;z<len;z++){
        while(buf[z]!=32&&z<len-1){
            filename[i] = buf[z];
            i++;
            z++;
            if(buf[z]==32||z==len-1){
                *closeflag=1;
                z=len;
            }
        }
    }
    puts(filename);
    if(*closeflag){
        if(order[0] == 'g' && order[1] == 'e' && order[2] == 't' && order[3] == 's'){
            int filefd = open(filename,O_RDWR);
            if(-1==filefd){
                filefd = open(filename,O_RDWR|O_CREAT,0666);
            }
            getsfunc(clientfd,filefd);
        }else if(order[0] == 'p' && order[1] == 'u' && order[2] == 't' && order[3] == 's'){
            int filefd = open(filename,O_RDWR);
            putsfunc(clientfd,filefd);
        }
    }
}
void getsfunc(int clientfd,int filefd){
    int ret;
    off_t filexistmark = 0; //用于记录文件当前位置，及偏移量
    struct stat file_stat;
    fstat(filefd,&file_stat);
    filexistmark = file_stat.st_size;

    //接受文件总大小
    int filesizeoflength = 0;
    off_t filesize = 0;
    ret = recv(clientfd,&filesizeoflength,4,MSG_WAITALL);
    printf(">>>>>>>>>>>>filesizeoflenth%d\n",filesizeoflength);
    ret = recv(clientfd,&filesize,filesizeoflength,MSG_WAITALL);
    printf(">>>>>>>>>>>>filesize:%ld\n",filesize);
    
    //发送偏移量
    ret = send(clientfd,&filexistmark,8,0);
    printf("send %d charactor\n",ret);
    printf("send file offset:%ld\n",filexistmark);
    
    off_t filesurplus = filesize - filexistmark;
    //判断大文件小文件
    if(filesurplus < (long)100* 1024){
        printf("small file\n");
        lseek(filefd,SEEK_SET,filexistmark);
        getsFunction_smallfile(clientfd,filefd,filesurplus);
    }else{
        printf("big file\n");
        ftruncate(filefd,filesize);
        printf("ftruncate");
        getsFunction_bigfile(clientfd,filefd,filesize,filexistmark);
    }

}
void getsFunction_smallfile(int clientfd,int filefd,off_t filesize){
    char buf[1024] = {0};
    memset(buf,0,1024);
    int retval;
    off_t slice = filesize/100;
    off_t downloadsize=0;
    off_t lastsize = 0;
    while(downloadsize<filesize){
        memset(buf,0,sizeof(buf));
        retval = recv(clientfd,buf,sizeof(buf),0);
        downloadsize+=retval;
        if(downloadsize - lastsize>slice){
            printf(">> download percent:%5.2lf%%\n",(double)downloadsize/filesize*100);
            lastsize = downloadsize;
        }
        retval = write(filefd,buf,retval);
        ERROR_CHECK(retval,-1,"write");
    }
    printf(">>download percent:100%%\n");
    printf("getsfunc is over!\n");
    close(filefd);
}
void getsFunction_bigfile(int clientfd,int filefd,off_t filesize,off_t filexistmark){
            //接受文件
        char * pbuf = (char *) mmap(NULL,filesize,PROT_READ | PROT_WRITE, MAP_SHARED, filefd, 0);

        int ret = recv(clientfd,pbuf + filexistmark,filesize - filexistmark,MSG_WAITALL);
        printf("recvn:%d charactor\n",ret);
        perror("big file recv");
        printf("recv big file over\n");
        close(filefd);
        munmap(pbuf,filexistmark );
}
void putsfunc(int clientfd,int filefd){
    char buf[1024] = {0};
    memset(buf,0,sizeof(buf));
    recv(clientfd,buf,sizeof(buf),0);
    puts(buf);
    memset(buf,0,sizeof(buf));
    int ret;
    train_t train;

    //发送长度
    memset(&train,0,sizeof(train));
    struct stat file_stat;
    fstat(filefd,&file_stat);
    off_t filesize = file_stat.st_size;
    train.length = sizeof(off_t);
    strncpy(train.date,(char*)&filesize,train.length);
    ret = sendn(clientfd,&train,4 + train.length);
    printf("file length:%ld\n",file_stat.st_size);
    
    //接受文件偏移量
    off_t filexistmark = 0;
    ret = recv(clientfd,&filexistmark,8,0);
    printf("recv file offset:%ld\n",filexistmark);
    
    off_t filesurplus = filesize - filexistmark;
    
    //传文件选择
    if(filesurplus < (long)100*1024){
        printf("small file\n");
        lseek(filefd,SEEK_SET,filexistmark);
        putsFunction_smallfile(clientfd,filefd,filesurplus);
    }else{
        printf("big file\n");
        putsFunction_bigfile(clientfd,filefd,filesize,filexistmark);
    }

}
int sendn(int fd, const void * buf, int len)
{
    int left = len;
    char * pbuf = (char *)buf;
    int ret;
    while(left > 0) {
        ret = send(fd, pbuf, left, 0);
        if(ret < 0) {
            perror("send");
            break;
        } else {
            pbuf += ret;
            left -= ret;
        }
    }
    return len - left;
}
void putsFunction_bigfile(int clientfd,int filefd,off_t filesize,off_t filexistmark)
{
    int ret = 0;
    //发送文件内容
    char * pbuf = (char *)mmap(NULL,
            filesize,PROT_READ | PROT_WRITE,MAP_SHARED, filefd, 0);
    ret = send(clientfd,pbuf+filexistmark,filesize - filexistmark,MSG_WAITALL);
    printf("big file send over!\n");
    close(filefd);
    munmap(pbuf, filesize);

}

void putsFunction_smallfile(int clientfd, int filefd, off_t filesize){
    printf("clientfd:%d,filefd:%d,filesize:%ld\n",clientfd,
           filefd,filesize);
    train_t train;
    memset(&train,0,sizeof(train));
    printf("begin!\n");
    char buf[1024]={0};
    memset(buf,0,sizeof(buf));
    off_t sendsize = 0;
    while(sendsize<filesize){
        int retval = read(filefd,buf,sizeof(buf));
        retval = send(clientfd,buf,retval,0);
        printf("retval:%d\n",retval);
        sendsize+=retval;
        memset(buf,0,sizeof(buf));
    }
    close(filefd);
    printf("file send over!\n");
}
void LoginInterface()
{
    printf("****************************************\n");
    printf("****************************************\n");
    printf("**********1.user login        **********\n");
    printf("**********2.user register     **********\n");
    printf("****************************************\n");
    printf("****************************************\n");
    printf("please input your choice:\n");
}